package Ga.Implementations.Points;

import Ga.Design.GeneticAlgorithm;
import Ga.Design.IIndividual;

public class Point implements IIndividual
{
	private int MAX_COORD_X = 100;
	private int MAX_COORD_Y = 100;
	
	private int x, y;
	
	public Point()
	{
		this.x = GeneticAlgorithm.randomGenerator.nextInt(this.MAX_COORD_X);
		this.y = GeneticAlgorithm.randomGenerator.nextInt(this.MAX_COORD_Y);
	}
	
	public Point(int x, int y)
	{
		this.x = x;
		this.y = y;
	}
	
	public int getX() { return this.x; }
	public int getY() { return this.y; }

	public IIndividual CrossOver(IIndividual point)
	{
		Point parent = (Point)point;
		Point child = (Point)this.clone();
		if(GeneticAlgorithm.randomGenerator.nextInt(2) == 0)
			child.x = parent.getX();
		else
			child.y = parent.getY();
		
		return child;
	}
	
	public float getFitness()
	{
		/*
		float div = (float)(x + y);

		if(div > 0)
			return x / this.MAX_COORD_X;
		else
			return 1;
		*/
		
		return (float)x / (float)this.MAX_COORD_X;
	}
	
	public void Mutate()
	{
		if(GeneticAlgorithm.randomGenerator.nextInt(2) == 0)
		{			
			int delta = GeneticAlgorithm.randomGenerator.nextInt(this.MAX_COORD_X/10);
			if(GeneticAlgorithm.randomGenerator.nextInt(2) == 0)
				this.setX(this.x - delta);
			else
				this.setX(this.x + delta);
		}
		else
		{
			int delta = GeneticAlgorithm.randomGenerator.nextInt(this.MAX_COORD_Y/10);
			if(GeneticAlgorithm.randomGenerator.nextInt(2) == 0)
				this.setY(this.y - delta);
			else
				this.setY(this.y + delta);
		}
	}
	
	private void setX(int x)
	{
		if(x >= 0 && x <= this.MAX_COORD_X)
			this.x = x;		
	}

	private void setY(int y) 
	{
		if(y >= 0 && y <= this.MAX_COORD_Y)
			this.y = y;		
	}

	
	public Object clone()
	{
		return new Point(this.x, this.y);
	}
	
	public String toString()
	{
		return "(" + this.x + ", " + this.y + ") = " + this.getFitness();
	}
	
	/// Descending Ordering
	public int compareTo(IIndividual point)
	{
		if(this.getFitness() > point.getFitness())
			return -1;
		else if(this.getFitness() < point.getFitness())
			return 1;
		else
			return 0;
	}
}
